package com.dhemery.mack.model.tests;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.dhemery.mack.model.Folder;
import com.dhemery.mack.model.FolderChangeListener;
import com.dhemery.mack.model.Node;
import com.dhemery.mack.model.Page;

public class FolderChangeNotificationTests {

	@Test
	public void notifiesListenerOnAdd() {
		FakeFolderChangeListener listener = new FakeFolderChangeListener();
		Folder.subscribeToChildChange(listener);
		Folder folder = new Folder();
		Page page = new Page();

		folder.addNode(page);

		assertEquals(1, listener.getAddNotificationCount());
		assertEquals(folder, listener.getAddNotificationFolder(1));
		assertEquals(page, listener.getAddNotificationNode(1));
	}

	@Test
	public void notifiesListenerOnEachAdd() {
		FakeFolderChangeListener listener = new FakeFolderChangeListener();
		Folder.subscribeToChildChange(listener);
		Folder folder1 = new Folder();
		Folder folder2 = new Folder();
		Page page1 = new Page();
		Page page2 = new Page();
		Page page3 = new Page();

		folder1.addNode(page1);
		folder2.addNode(page2);
		folder2.addNode(page3);

		assertEquals(3, listener.getAddNotificationCount());
		assertEquals(folder1, listener.getAddNotificationFolder(1));
		assertEquals(page1, listener.getAddNotificationNode(1));
		assertEquals(folder2, listener.getAddNotificationFolder(2));
		assertEquals(page2, listener.getAddNotificationNode(2));
		assertEquals(folder2, listener.getAddNotificationFolder(3));
		assertEquals(page3, listener.getAddNotificationNode(3));
	}

	@Test
	public void notifiesEachListenerOnAdd() {
		FakeFolderChangeListener listener1 = new FakeFolderChangeListener();
		FakeFolderChangeListener listener2 = new FakeFolderChangeListener();
		FakeFolderChangeListener listener3 = new FakeFolderChangeListener();
		Folder.subscribeToChildChange(listener1);
		Folder.subscribeToChildChange(listener2);
		Folder.subscribeToChildChange(listener3);

		new Folder().addNode(new Page());

		assertEquals(1, listener1.getAddNotificationCount());
		assertEquals(1, listener2.getAddNotificationCount());
		assertEquals(1, listener3.getAddNotificationCount());
	}

	class FakeFolderChangeListener implements FolderChangeListener {
		private List<Folder> addNotificationFolders = new ArrayList<Folder>();
		private List<Node> addNotificationNodes = new ArrayList<Node>();
		private List<Folder> removeNotificationFolders = new ArrayList<Folder>();
		private List<Node> removeNotificationNodes = new ArrayList<Node>();

		public void nodeAdded(Folder folder, Node node) {
			addNotificationFolders.add(folder);
			addNotificationNodes.add(node);
		}

		public void nodeRemoved(Folder folder, Node node) {
			removeNotificationFolders.add(folder);
			removeNotificationNodes.add(node);
		}

		public int getAddNotificationCount() {
			return addNotificationFolders.size();
		}

		public Folder getAddNotificationFolder(int n) {
			return addNotificationFolders.get(n-1);
		}

		public Node getAddNotificationNode(int n) {
			return addNotificationNodes.get(n-1);
		}

		public int getRemoveNotificationCount() {
			return removeNotificationFolders.size();
		}

		public Folder getRemoveNotificationFolder(int n) {
			return removeNotificationFolders.get(n-1);
		}

		public Node getRemoveNotificationNode(int n) {
			return removeNotificationNodes.get(n-1);
		}
	}
}
